/**
 *  This file is part of Bioinformatics Sequence Comparison Game.
 *
 *  Bioinformatics Sequence Comparison Game is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Bioinformatics Sequence Comparison Game is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Bioinformatics Sequence Comparison Game.  If not, see <http://www.gnu.org/licenses/>.
 *  
 *  @author Eric Augustine
 *  @author Jim Jensen
 *  @author Spencer Vanderpoel
 *  @author Corban McCammon
 *  @author Brett Penza
 *  @version 1.0.0
 */
package com.project.BSCG1;

import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

/*
 * Runs the main game for single player mode
 */
public class GameActivity extends Activity{
	
	private TextView userName; //Text field that contains the user's name
	private Game game; //Game Data structure associated with this activity
	private Button Deck; //Button that activates deck related functionality (i.e drawing)
	private Button DiscardPile; //Button for discard related functionality (i.e discarding, drawing)
	private Button knock; //Button for initiating a knock
	private TextView currentScore; //Keeps track of players current score
	private int currentPlayer = 0; //REMOVE
	private ArrayList<Button> cards = new ArrayList<Button>(16); //All the buttons for the single player cards in a list
	private int cardsPicked = 0; //Number of cards face up
	private boolean deckClicked = false; //Whether the deck was clicked
	private HashMap<String, Integer> drawables = new HashMap<String, Integer>();// links amino String to its drawable identity
	private Score score; //Holds the score map for this game
	private boolean firstTurn = true; //Keeps track of whether they have had their firstTurn
	private boolean firstDraw = true; //Keeps track of players first draw
	private boolean firstDiscard = true; //Keeps track of players first discard
	private boolean tutorialMode; //Keeps track of whether tutorial mode is enabled
	
	/*
	 * Sets up the layout for the game and starts the game
	 */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.singleplayer); //Sets the XML for single player view
		startGame();
    }
    
    /*
     * Initializes game starting conditions and prompts the user with how many cards to turn face up
     */
    private void startGame(){
    	score = new Score();
    	
    	// set up drawables HashMap
    	setDrawablesMap();
    	
    	//Find userName text field
    	userName = (TextView)findViewById(R.id.UserName);
    	currentScore = (TextView)findViewById(R.id.CurrentScore);
        
    	//Get the intent
    	Intent main = getIntent();
        
    	//And grab the bundle containing the user information out of it
    	Bundle userInfo = main.getExtras();
    	
    	//Get the userName out of the bundle
        String player1 = userInfo.getString("userName");
        tutorialMode = userInfo.getBoolean("TutorialMode");
        
        //Set the text field to display the user name
        userName.setText(player1 + " ");
        
        //Create a new game with all players
        ArrayList<String> players = new ArrayList<String>();
        players.add(player1);
        game = new Game(1,players);
        game.getPlayers().get(0).setUserName(player1);
        
        //Display top of the discard Pile
        updateDiscardField();
        
        gameObjectivesPrompt();
        
    }
    
    private void turnCardsFaceUpPrompt(){
    	//Inform users of how many cards they can turn face up
        AlertDialog.Builder turnCardsFaceUp = new AlertDialog.Builder(this);

		turnCardsFaceUp.setTitle("Turn");
		turnCardsFaceUp.setMessage("Tap six cards to turn them face up.");

		turnCardsFaceUp.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int whichButton) {}});
		turnCardsFaceUp.show();
    }
    
    private void gameObjectivesPrompt(){
    	AlertDialog.Builder objectives = new AlertDialog.Builder(this);
    	
    	objectives.setTitle("Game Objectives");
    	objectives.setMessage("The objective of this game \nis to match amino acids vertically. \nTo acheive the highest score possible, \nmatch amino acids based on their similarity.");

    	objectives.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int whichButton) {
	        //Set up card buttons for turning cards face up
	        initCardButtons(currentPlayer);
			turnCardsFaceUpPrompt();
		}});
    	objectives.show();
    }
    
    @Override
    protected void onStart(){
    	super.onStart();
    }
    @Override
    protected void onResume() {
        super.onResume();
    }
    @Override
    protected void onPause() {
        super.onPause();
    }
    @Override
    protected void onStop() {
        super.onStop();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    
    /*
     * Find the ids for all 16 of the card buttons add them to the cards arraylist
     * and set their on click listeners
     */
    private void initCardButtons(int player){
    	cards.add((Button)findViewById(R.id.Card1));
    	cards.add((Button)findViewById(R.id.Card2));
    	cards.add((Button)findViewById(R.id.Card3));
    	cards.add((Button)findViewById(R.id.Card4));
    	cards.add((Button)findViewById(R.id.Card5));
    	cards.add((Button)findViewById(R.id.Card6));
    	cards.add((Button)findViewById(R.id.Card7));
    	cards.add((Button)findViewById(R.id.Card8));
    	cards.add((Button)findViewById(R.id.Card9));
    	cards.add((Button)findViewById(R.id.Card10));
    	cards.add((Button)findViewById(R.id.Card11));
    	cards.add((Button)findViewById(R.id.Card12));
    	cards.add((Button)findViewById(R.id.Card13));
    	cards.add((Button)findViewById(R.id.Card14));
    	cards.add((Button)findViewById(R.id.Card15));
    	cards.add((Button)findViewById(R.id.Card16));
    	
    	for(int i = 0; i < cards.size(); i++){
    		final PlayerAndCard p = new PlayerAndCard(player,i);
    		cards.get(i).setOnClickListener(new Button.OnClickListener(){
    			public void onClick(View v) {
    				initCards(p.getPlayerNum(),p.getCardNum());
    			}});
    	}
    }
    
    /*
     * Sets the card buttons text to the card located at that position in the 
     * players hand and when 8 cards are turned up, disable the card buttons and start the turn phase
     */
    private void initCards(int player, int cardPos){
    	if(game.getPlayers().get(player).getPlayersHand().getCardTurn(cardPos) == false) {
    		String amino = game.getPlayers().get(player).getPlayersHand().getCard(cardPos).getAminoAcid();
			cards.get(cardPos).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			game.getPlayers().get(player).getPlayersHand().setCardTurn(cardPos);
		
			cardsPicked++;
			if(cardsPicked >= 6) {
				disableCardButtons();
				turn();
			}
    	}
    }
    
    /*
     * Sets the onClick listeners of all the card buttons to nothing
     */
    private void disableCardButtons(){
    	for(int card = 0; card <= 15; card++){
    		cards.get(card).setOnClickListener(new Button.OnClickListener(){
    			public void onClick(View v){}
    		});
    	}
    }
    /*
     * Sets the card buttons to replace cards in the hand based on based on the card clicked
     */
    private void enableCardButtons(int player){
    	for(int i = 0; i < cards.size(); i++){
    		final PlayerAndCard p = new PlayerAndCard(player,i);
    		cards.get(i).setOnClickListener(new Button.OnClickListener(){
    			public void onClick(View v) {
    				setCard(p.getPlayerNum(),p.getCardNum());
    			}});
    	}
    }
    
    /*
     * Sets the card of a players hand based on whether the deck or discard pile
     */
    private void setCard(int player, int cardPosition){
    	//If the deck was clicked
    	if(deckClicked){
    		//Grabs the current card in the players hand based on the card clicked
			Card currentCard = game.getPlayers().get(player).getPlayersHand().getCard(cardPosition);
			
			//Replace that place in the hand with the top of the deck
			game.getPlayers().get(player).getPlayersHand().replaceCard(game.getDeck().drawCard(), cardPosition);
			
			//Push the card replaced on top of the discard pile
			game.getDiscardPile().pushCard(currentCard);
			
			//Set the DiscardPile button to the new top of the discardPile
			DiscardPile.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
			
			//If the card was face down, increment the number of cards now face up
			if(game.getPlayers().get(player).getPlayersHand().getCardTurn(cardPosition) == false) {
				game.getPlayers().get(player).getPlayersHand().setCardTurn(cardPosition);
				cardsPicked++;
			}
			
			//Set the card button to the new card located at that position in the hand
			cards.get(cardPosition).setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getPlayers().get(player).getPlayersHand().getCard(cardPosition).getAminoAcid())));

			if(game.getDeck().isEmpty()){
				Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.outline));
			}else{
				Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.parkside_back1));
			}
			
			//Disable the card buttons
			disableCardButtons();
			
			//Disable the discard button so it cant be clicked again until the next turn
			disableDiscard();
		}else{
			
			//Get the current card at the position clicked in the players hand
			Card currentCard = game.getPlayers().get(player).getPlayersHand().getCard(cardPosition);
			
			//Replace that card with the top card of the discard pile
			game.getPlayers().get(player).getPlayersHand().replaceCard(game.getDiscardPile().drawCard(), cardPosition);
			
			//Update the discard pile
			game.getDiscardPile().pushCard(currentCard);
			
			//Set the new text of the top card of the discard Pile
			DiscardPile.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
			
			//If the card was face down, increment the number of cards now face up
			if(game.getPlayers().get(player).getPlayersHand().getCardTurn(cardPosition) == false) {
				game.getPlayers().get(player).getPlayersHand().setCardTurn(cardPosition);
				cardsPicked++;
			}
			
			//Set text of the card at the position clicked
			cards.get(cardPosition).setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getPlayers().get(player).getPlayersHand().getCard(cardPosition).getAminoAcid())));

			//Disable Card buttons
			disableCardButtons();
			//Disable discard buttons
			disableDiscard();
		}
    	
    	//Call next turn
    	turn();
    }
    
    /*
     * Disable discardPile
     */
    private void disableDeck(){
    	Deck.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
			}});
    }
    
    /*
     * Initializes Controls at the beginning of the turn
     */
    private void initControls(){
    	Deck = (Button)findViewById(R.id.Deck);
    	DiscardPile = (Button)findViewById(R.id.DiscardPile);
    	knock = (Button)findViewById(R.id.knock);
    	
    	//Ends game and scores when all cards are face up and displays score
    	if(cardsPicked > 15){
    		endGame();
    	}
    	else {
    		//Set the onclick listener of the deck
    		Deck.setOnClickListener(new Button.OnClickListener(){
    			public void onClick(View v) {
    				deckClicked = true;
    				//If the deck isn't empty, display top card of deck and enable card buttons
    				if(!game.getDeck().isEmpty()) {
    					Deck.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDeck().peekAtTop().getAminoAcid())));
    					deckClicked();
    					enableCardButtons(currentPlayer);
    				//If the deck is emptied, end the game and display the score
    				} else {
    					endGame();
    				}
    			}});
    		//Set the onClick listener of the discard pile
    		DiscardPile.setOnClickListener(new Button.OnClickListener(){
    			//If the discard pile is clicked at start of turn, disable the deck and disable the discard pile
    			//Then enable all card buttons
    			public void onClick(View v) {
    				if(firstDiscard && tutorialMode){
    		    		discardClicked();
    		    	}
    				deckClicked = false;
    				if(game.getDiscardPile().peekAtTop() != null){
    					disableDeck();
    					disableDiscard();
    					enableCardButtons(currentPlayer);
    				}else{
    					DiscardPile.setBackgroundDrawable(getResources().getDrawable(R.drawable.outline));
    				}
    			}});
    		knock.setOnClickListener(new Button.OnClickListener(){
    			//Set the player who knocked in the game,
    			//and ends the game for single player
    			public void onClick(View v) {
    				game.knock(game.getPlayers().get(currentPlayer));
    				endGame();
    			}});
    	}
    }
    
    /*
     * Tutorial prompt for when the discard is clicked
     */
    private void discardClicked(){
    		AlertDialog.Builder discardSelected = new AlertDialog.Builder(this);

    		discardSelected.setTitle("Pick a card to replace");
    		discardSelected.setMessage("Tap one of your cards to replace with top card of discard pile.");

    		discardSelected.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    		public void onClick(DialogInterface dialog, int whichButton) {}});
    		discardSelected.show();	
    		firstDiscard = false;
    }
    
    /*
     * If the deck is clicked, disable the deck and set the discard pile so that you can discard from the
     * top of the deck
     */
    private void deckClicked(){
    	//Show the tutorial prompt for the firstDraw
    	if(firstDraw && tutorialMode){
    		AlertDialog.Builder deckSelected = new AlertDialog.Builder(this);

    		deckSelected.setTitle("Select a card to replace or discard");
    		deckSelected.setMessage("Tap one of your cards to replace drawn card or tap on the discard pile to discard drawn card.");

    		deckSelected.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    		public void onClick(DialogInterface dialog, int whichButton) {}});
    		deckSelected.show();	
    		firstDraw = false;
    	}
    	Deck.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
			}});
    	DiscardPile.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
				game.getDiscardPile().pushCard(game.getDeck().drawCard());
				if(game.getDeck().isEmpty()){
					Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.outline));
				}else{
					Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.parkside_back1));
				}
				DiscardPile.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
				disableDiscard();
				disableCardButtons();
				turn();
			}});
    }
    
    /*
     * Disables discard
     */
    private void disableDiscard(){
    	DiscardPile.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
			}});
    }
    
    /*
     * Updates text of the discard pile
     */
    private void updateDiscardField(){
    	Button discard = (Button)findViewById(R.id.DiscardPile);
    	discard.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
    }
    /*
     * This method creates the drawables HashMap
     */
    private void setDrawablesMap() {
    	drawables.put("A", R.drawable.a_card);
    	drawables.put("C", R.drawable.c_card);
    	drawables.put("D", R.drawable.d_card);
    	drawables.put("E", R.drawable.e_card);
    	drawables.put("F", R.drawable.f_card);
    	drawables.put("G", R.drawable.g_card);
    	drawables.put("H", R.drawable.h_card);
    	drawables.put("I", R.drawable.i_card);
    	drawables.put("K", R.drawable.k_card);
    	drawables.put("L", R.drawable.l_card);
    	drawables.put("M", R.drawable.m_card);
    	drawables.put("N", R.drawable.n_card);
    	drawables.put("P", R.drawable.p_card);
    	drawables.put("Q", R.drawable.q_card);
    	drawables.put("R", R.drawable.r_card);
    	drawables.put("S", R.drawable.s_card);
    	drawables.put("T", R.drawable.t_card);
    	drawables.put("V", R.drawable.v_card);
    	drawables.put("W", R.drawable.w_card);
    	drawables.put("Y", R.drawable.y_card);
    }
    
    /*
     * Initializes the controls
     */
    private void turn(){
    	updateCurrScore();
    	
    	if(firstTurn && tutorialMode){
    		AlertDialog.Builder selectPile = new AlertDialog.Builder(this);

    		selectPile.setTitle("Select a Card from the Deck or Discard Pile");
    		selectPile.setMessage("Tap the deck to draw a card or click on the discard pile to use the top card from the discard pile.");

    		selectPile.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    		public void onClick(DialogInterface dialog, int whichButton) {}});
    		selectPile.show();
    		firstTurn = false;
    	}
    	initControls();
    }
    
    /*
     * Scores the hand of all the players and computes the highest score
     */
    private void endGame(){
    	for(int i = 0; i < game.getPlayers().size(); i++){
    		boolean[] cardsUp = game.getPlayers().get(i).getPlayersHand().getTurnUp();
    		for(int j = 0; j < cardsUp.length; j++){
    			if(!cardsUp[j]){
    				cards.get(j).setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getPlayers().get(i).getPlayersHand().getCard(j).getAminoAcid())));
    				game.getPlayers().get(i).getPlayersHand().setCardTurn(j);
    			}
    		}
    	}
	    	
    	for(int i = 0; i < game.getPlayers().size(); i++){
    		game.getPlayers().get(i).setScore(score.scoreHand((game.getPlayers().get(i))));
    	}
    	updateCurrScore();
    	
    	AlertDialog.Builder scorePrompt = new AlertDialog.Builder(this);

    	scorePrompt.setTitle(game.getPlayers().get(0).getUserName() + "'s Score");
    	scorePrompt.setMessage("Your score is " + game.getPlayers().get(0).getScore());

    	scorePrompt.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int whichButton) {
			finish();
		}});
    	scorePrompt.show();
    }
    
    /*
     * Updates the current score of the player
     */
    private void updateCurrScore(){
    	ArrayList<String> adjCards = game.getPlayers().get(currentPlayer).getPlayersHand().currentAdjacentCardsFaceUp();
    	int currScore = score.currentScore(adjCards);
    	currentScore.setText(currScore + "");
    }
}
